<?php
namespace Lib;

/**
 * 利用此类完成浏览器的区分时，常规的思想如下：
 *
 * 1 检查浏览器是否为 MSIE，若是，则确定其版本后结束；
 * 2 检查浏览器渲染引擎是否为 Gecko，若是，则结束；
 * 3 检查浏览器渲染引擎是否为 Webkit，若是，则结束；
 * 4 检查浏览器渲染引擎是否为 Presto，若是，则结束；
 * 5 检查浏览器渲染引擎是否为 KHTML，若是，则结束；
 * 6 检查浏览器渲染引擎是否为 UCWeb，若是，则结束；
 * 7 检查操作系统是否为 J2ME，若是，则结束；
 * 8 未知浏览器；
 *
 * @author SUSISOY
 *
 */
class Browser {
	private $agent = '';
	
	private $robots = array('googlebot' => 'Google', 'baiduspider' => 'Baidu', 'msnbot' => 'Bing', 'yahoo' => 'Yahoo', 'sosospider' => 'SOSO', 'yodaobot' => 'Yodao', 'sogou' => 'Sogou', 'dotbot' => 'Dotbot');
	/**
	 * 注意定义顺序，比如“Android”在“Linux”之前是因为 Android 的 User-Agent 中存在“Linux”内容，而 Linux 的 User-Agent 中并不存在“Android”内容
	 * @var array
	 * @access private
	 */
	private $systems = array('windows nt 6.1' => 'Windows 7', 'windows nt 6.0' => 'Windows Vista', 'windows nt 5.2' => 'Windows 2003', 'windows nt 5.1' => 'Windows XP', 'windows nt 5.0' => 'Windows 2000', 'series60' => 'Symbian S60', 'android' => "Android", 'ipad' => 'iPad', 'ipod' => 'iPod', 'iphone' => 'iPhone', 'mac os x' => 'Mac OS X', 'windows ce' => "Windows Mobile", 'linux' => 'Linux', 'unix' => 'Unix', 'midp' => 'J2ME', 'cldc' => 'J2ME');
	/**
	 * 注意定义顺序，比如“Chrome”在“Safari”之前是因为 Chrome 的 User-Agent 中存在“Safari”内容，但 Safari 的 User-Agent 中并不存在“Chrome”内容
	 * @var array
	 * @access private
	 */
	private $browsers = array('msie' => 'MSIE', 'firefox' => 'Firefox', 'chrome' => 'Chrome', 'safari' => 'Safari', 'opera' => 'Opera', 'konqueror' => 'Konqueror', 'ucweb' => 'UCWeb');
	
	/**
	 * 单例模式，总是默认初始化当前客户端浏览器的  User-Agent 内容，若需要初始化另一条  User-Agent 内容，则再次调用 setUserAgent() 方法
	 *
	 */
	private function __construct() {
		$this->setUserAgent($_SERVER['HTTP_USER_AGENT']);
	}
	
	/**
	 * 初始化一条 User-Agent 内容
	 *
	 * @param string $agent
	 * @return boolean
	 */
	public function setUserAgent($agent) {
		if (!$agent) {
			return false;
		}
		
		$this->agent = strtolower($agent);
		
		return true;
	}
	
	/**
	 * 获得 User-Agent 中的相关信息
	 *
	 * @param string $name
	 * @return mixed
	 */
	public function __get($name) {
		switch (strtolower($name)) {
			case 'engine' :
				return $this->getEngine();
			case 'browser' :
				return $this->getBrowser();
			case 'version' :
				return $this->getVersion();
			case 'system' :
				return $this->getSystem();
			case 'robot' :
				return $this->getRobot();
		}
	}
	
	/**
	 * 是否为移动设备，比如手机等，而非移动设备一定是计算机（PC、笔记本、服务器等）
	 *
	 * @return boolean
	 */
	public function isMobile() {
		static $keyword = array('nokia', 'symbian', 'iphone', 'android', 'ipod', 'ipad', 'htc', 'samsung', 'midp', 'cldc', 'windows ce', 'opera mini', 'ucweb');
		
		foreach ($keyword as $value) {
			if (strpos($this->agent, $value) !== false) {
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * 是否为搜索引擎机器人，若非搜索引擎机器人，则一定是浏览器
	 *
	 * @return boolean
	 */
	public function isRobot() {
		return $this->getRobot() != '';
	}
	
	/**
	 * 获得 User-Agent 的操作系统名称，比如 Windows 7，Symbian S60 等
	 *
	 * @return string
	 */
	private function getSystem() {
		if (preg_match('/Mozilla\/[\d\.]+ \((\w+)/i', $this->agent, $match)) {
			$match[1] = strtolower($match[1]);
			
			if ($match[1] && $match[1] != 'linux' && $this->systems[$match[1]]) {
				return $this->systems[$match[1]];
			}
		}
		
		foreach ($this->systems as $key => $value) {
			if (strpos($this->agent, $key) !== false) {
				return $value;
			}
		}
		
		return '';
	}
	
	/**
	 * 获得 User-Agent 的浏览器名称，比如 MSIE，Firefox 等
	 *
	 * @return string
	 */
	private function getBrowser() {
		foreach ($this->browsers as $key => $value) {
			if (preg_match("/{$key}.*?([0-9\.]+)/i", $this->agent, $match)) {
				if ($key == 'safari' && !preg_match("/version\\/[0-9\\.]+/i", $this->agent)) {
					continue;
				}
				
				return $value;
			}
		}
		
		return '';
	}
	
	/**
	 * 获得 User-Agent 的浏览器版本号，所得版本号可使用 version_compare() 进行比较
	 *
	 * @return string
	 */
	private function getVersion() {
		$browser = $this->getBrowser();
		
		if (!$browser) {
			return '';
		}
		
		$browser = array_search($browser, $this->browsers);
		
		if ($browser == 'safari') {
			if (preg_match("/version\\/([0-9\\.]+)/i", $this->agent, $match)) {
				return $match[1];
			}
			
			return '';
		}
		
		if (preg_match("/{$browser}.*?([0-9\.]+)/i", $this->agent, $match)) {
			return $match[1];
		}
		
		return '';
	}
	
	/**
	 * 获得 User-Agent 的搜索引擎机器人名称，比如 Google，Baidu 等
	 *
	 * @return string
	 */
	private function getRobot() {
		foreach ($this->robots as $key => $value) {
			if (strpos($this->agent, $key) !== false) {
				return $value;
			}
		}
		
		return '';
	}
	
	/**
	 * 获得 User-Agent 的渲染引擎名称，如 Trident、Gecko、Webkit 等
	 *
	 * @return string
	 */
	private function getEngine() {
		switch ($this->browser) {
			case $this->browsers['msie'] :
				return 'Trident';
			case $this->browsers['firefox'] :
				return 'Gecko';
			case $this->browsers['safari'] :
			case $this->browsers['chrome'] :
				return 'Webkit';
			case $this->browsers['opera'] :
				return 'Presto';
			case $this->browsers['konqueror'] :
				return 'KHTML';
			case $this->browsers['ucweb'] :
				return 'UCWeb';
		}
		
		if (strpos($this->agent, 'trident') !== false) {
			return 'Trident';
		} elseif (strpos($this->agent, 'applewebkit') !== false) {
			return 'Webkit';
		} elseif (strpos($this->agent, 'gecko') !== false) {
			return 'Gecko';
		} elseif (strpos($this->agent, 'presto') !== false) {
			return 'Presto';
		} elseif (strpos($this->agent, 'khtml') !== false) {
			return 'KHTML';
		} elseif (strpos($this->agent, 'ucweb') !== false) {
			return 'UCWeb';
		}
		
		return '';
	}
	
	/**
	 * 单例模式
	 *
	 */
	static public function getInstance() {
		static $instance = null;
		
		$instance || ($instance = new self());
		
		return $instance;
	}
}